package com.guaoran.interview.in2018.jvm;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

/**
 * @author : guaoran
 * @Description : <br/>
 *  引用
 * @date :2018/12/20 22:22
 */
public class ReferenceDemo {
    public static void main(String[] args) throws InterruptedException {
//        strongReference();
//        softReference();
//        weakReference();
        phantomReference();
    }



    /**
     * 强引用
     * 只要引用存在，垃圾回收器永远不会回收，即使内存溢出也不会回收
     */
    public static void strongReference(){
        Object strongRefObj = new Object();
        //除非手动设置为null
        //strongRefObj = null;
        System.gc();
        System.out.println(strongRefObj);
    }

    /**
     * 软引用
     * 内存溢出之前进行回收，
     */
    public static void softReference(){
        Object softRefObj = new Object();
        SoftReference reference = new SoftReference(softRefObj);
//        softRefObj = null;
//        System.gc();
        System.out.println(reference.get());
    }
    /**
     * 弱引用：
     * 当非final修饰的对象设置为空时，gc的时候才会被回收，
     * jvm回收的时候不会回收常量池的对象，而final修饰的对象存在常量池中，如String
     */
    public static void weakReference(){
        Object weakRefObj = new Object();
        WeakReference reference = new WeakReference(weakRefObj);
        weakRefObj = null;
        System.gc();
        System.out.println(reference.get());
        String s = "123";
        WeakReference reference2 = new WeakReference(s);
        s = null;
        System.gc();
        System.out.println(reference2.get());
    }

    /**
     * 虚引用：
     * 垃圾回收时回收，无法通过引用取到对象值
     */
    public static void phantomReference() throws InterruptedException {
        Object phantomRefObj = new Object();
        ReferenceQueue queue = new ReferenceQueue();
        PhantomReference reference = new PhantomReference(phantomRefObj,queue);
        phantomRefObj = null;
        System.gc();
        Thread.sleep(200);
        //GC的时 ，会将虚引用放到队列里，
        System.out.println(queue.poll());
        System.out.println(reference.get());
    }
}
